<!--
  1.如何区分普通函数和构造函数？
        约定俗成的规矩:首字母大写的函数就是构造函数
        注意:
        1.一个函数只看函数声明是没办法分辨他到底是不是一个构造函数的
        2.只有被new调用的函数才是构造函数
-->

<!--
  前言:万物皆对象,除了基础数据类型外
  2.栈内存和堆内存
            栈内存:可以存储函数名/变量名,基础数据类型
            堆内存:可以存储对象类型数据
     注意:栈内存可以存储基础数据类型,
          但是基础数据类型不一定只能存在栈内存中,
          也可以存储在堆内存的对象的属性中
 -->

<!--
   3.原型:
        1.每个实例对象都有隐式原型属性(__proto__)
        2.每个构造函数都有显式原型属性(prototype)
          每个函数都有显式原型属性(prototype),
          只是如果不是构造函数就会失去用处,所以不做探讨
        3.每个实例对象的隐式原型都指向了构造函数的显式原型
        4.每个原型对象都具有constructor属性,用于指向对应的函数
        注意:每个函数都会伴生一个原型对象
  -->

<!--
  4.new做的事情
      1.声明形参,接收传入的实参数据,并将数据赋值给形参
      2.创建this变量(严格来说是个预留关键字),并向内注入一个对象
      3.将构造函数 !!!当前!!! 的显式原型属性值赋值给实例对象作为隐式原型属性值
      4.控制返回结果
          如果return的是基础数据类型,就会自动返回this对象
          如果return的是对象数据类型,就会返回该对象
 -->
<!--
   5.原型链：
   从对象的`__proto__`开始,
   连接的所有对象, 就是我们常说的原型链,
   也可称为`隐式原型链`
  -->

<script>
	//  情景
	function Dog(name) {
		var that = new Object();
		that.__proto__ = Dog.prototype;
		that.name = name;
		return that;
	}
	var d1 = Dog("皮卡");
	console.log("d1", d1);
</script>
